package cooperated

import (
	"errors"
	"fmt"
	"math/rand"

	"gddgame.cc/galaxy/common/namespaces/cooperate"
	"gddgame.cc/galaxy/common/namespaces/cooperate/structure"
	"gddgame.cc/galaxy/common/service/pathfinding"
	"gddgame.cc/galaxy/project/breeder/breeder/model"
	"gddgame.cc/galaxy/utils"
	"gddgame.cc/galaxy/utils/serialize"
)

const (
	_         = iota
	Update    // 更新信息
	Upgrade   // 升级信息
	Destroy   // 销毁信息
	UseDirect // 使用指令

	CreateUnit  // 创建部队
	MoveUnit    // 移动部队
	FlyUnit     // 传送部队
	CreateBuild // 创建建筑
	RobotUnit   // 托管部队
	ResetNode   // 更新节点
	PutUnit     // 投放部队
	DownUnit    // 撤退部队

	DependUpdate // 批量更新依赖

	ChangeTargetMode      // 调整目标模式
	ChangeAiMode          // 调整ai模式
	ChangeBehaviorPattern // 调整行为模式

	RandomPosition //
)

func (logic *TypeMap) OnQuery(accountId int, identity int, event byte, params []interface{}) interface{} {
	//fmt.Println("query", accountId, event, params)
	switch event {
	case Update:
		return logic.Update(accountId, utils.ToByte(params[0]), params[1], utils.ToString(params[2]))
	case Upgrade:
		return logic.Upgrade(accountId, utils.ToByte(params[0]), params[1], utils.ToInt(params[2]))
	case Destroy:
		return logic.Destroy(accountId, utils.ToByte(params[0]), params[1])
	case UseDirect:
		return logic.UseDirect(accountId, identity, utils.ToByte(params[0]), params[1], utils.ToInt(params[2]), utils.ToByte(params[3]), params[4], utils.ToInterfaceSlice(params[5]))
	case CreateUnit:
		return logic.CreateUnit(accountId, identity, utils.ToString(params[0]), utils.ToBytes(params[1]), utils.ToString(params[2]))
	case CreateBuild:
		return logic.CreateBuild(accountId, identity, utils.ToString(params[0]), utils.ToBytes(params[1]), utils.ToBytes(params[2]), utils.ToInt(params[3]), utils.ToString(params[4]), utils.ToByte(params[5]), params[6], utils.ToInterfaceSlice(params[7]))
	case MoveUnit:
		return logic.MoveUnit(utils.ToString(params[0]), utils.ToByte(params[1]), utils.ToByte(params[2]), params[3], nil)
	case FlyUnit:
		return logic.FlyUnit(accountId, identity, utils.ToString(params[0]), utils.ToBytes(params[1]), utils.ToBytes(params[2]))
	case PutUnit:
		return logic.PutUnit(accountId, identity, utils.ToStringSlice(params[0]), utils.ToBytes(params[1]))
	case DownUnit:
		return logic.DownUnit(accountId, identity, utils.ToStringSlice(params[0]))
	case RobotUnit:
		return logic.RobotUnit(accountId, identity, utils.ToString(params[0]), utils.ToBytes(params[1]), utils.ToBool(params[2]))
	case ResetNode:
		return logic.ResetNode(accountId, identity, utils.ToString(params[0]), utils.ToBytes(params[1]))
	case DependUpdate:
		return logic.DependUpdate(utils.ToByte(params[0]), params[1], utils.ToBytes(params[2]), utils.ToStringSliceSlice(params[3]), utils.ToString(params[4]))
	case ChangeTargetMode:
		return logic.ChangeTargetMode(accountId, utils.ToString(params[0]), TargetModeDefine(utils.ToInt(params[1])))
	case ChangeAiMode:
		return logic.ChangeAiMode(accountId, utils.ToString(params[0]), AiModeDefine(utils.ToInt(params[1])))
	case ChangeBehaviorPattern:
		return logic.ChangeBehaviorPattern(accountId, utils.ToString(params[0]), utils.ToInt(params[1]))
	case RandomPosition:
		return logic.GetRandomPosition(identity, utils.ToInt(params[0]), utils.ToBool(params[1]), utils.ToBool(params[2]))
	}
	return errors.New("Query miss " + utils.ToString(event))
}

func (logic *TypeMap) CreateUnit(id int, identity int, key string, position []byte, name string) interface{} {
	var fortress cooperate.PropsInstance
	if position != nil && len(position) > 0 {
		// 从据点获取
		fortress = logic.GetDetailCache(logic, structure.NewBaseData(FortressType, position))
		if fortress == nil {

		} else {
			if identity != fortress.ToInt(Identity) {
				return errors.New("据点被破坏")
			}
		}
	}
	level := 1
	unitId := logic.IncrTypeId(logic.GetMapNoId(), UnitType)
	result := structure.NewBaseData(UnitType, unitId)
	fd := logic.GetFieldsDefine(UnitType)
	instance := cooperate.NewPropInstance(logic, fd, result, map[string]interface{}{
		// 各个依赖项
		Id:              unitId,
		AccountDataType: id,
		Key:             key,
		Level:           level,
	})
	logic.directValidProcess(id, instance)
	owner := cooperate.NewAbilityOwner()
	effect := owner.Generate(logic, instance, logic)
	fmt.Println("unit effect", instance, effect, "key", key, position, identity)
	depends := []*cooperate.DependentItem{}
	if id > 0 {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AccountDataType,
			Depend: structure.NewBaseData(AccountType, id),
		})
	} else if fortress != nil {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AiFortress,
			Depend: structure.NewBaseData(FortressType, position),
		})
	} else {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AiForce,
			Depend: structure.NewBaseData(ForceType, identity),
		})
	}
	//fmt.Println("create unit", depends)
	create := &CreateTask{
		DataType: UnitType,
		Id:       unitId,
		Position: position,
		Key:      key,
		Identity: identity,
		Ability: &Ability{
			Level:         level,
			DirectAbility: effect.GetIds(model.DirectAbilityDefine),
			BuffAbility:   effect.GetIds(model.BuffAbilityDefine),
			AttrAbility:   effect.GetSlice(model.AttrAbilityDefine),
		},
		Depends: depends,
		Name:    name,
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(structure.NewBaseData(AccountType, id)).One(CreateTaskEvent, create).Task(0, nil)
	return unitId
}
func (logic *TypeMap) CreateBuild(id int, selfIdentity int, key string, position []byte, direction []byte, mode int, name string, t byte, dataId interface{}, params []interface{}) interface{} {
	baseData := structure.NewBaseData(structure.PublicDataType(t), dataId)

	buildId := logic.Center.TargetIdMap[BuildType][key]
	build := logic.Center.BuildMap[buildId]
	info := logic.GetDetailCache(logic, baseData)

	// 验证区域是否可用
	if err := logic.ValidPositions(position, build.FixRange); err != nil {
		fmt.Println("valid postion", err)
		return err
	}
	if baseData.DataType == UnitType {
		currentPosition := info.ToBytes(Position)
		// 不读就建造先移动后执行
		//fmt.Println("auto move")
		if move, err := logic.autoMove(build.FixRange, info, true, position, currentPosition, int(build.FixRange), logic.MakeQuery(id, selfIdentity, CreateBuild, []interface{}{key, position, direction, mode, name, t, dataId, params}, nil)); err != nil {
			fmt.Println("auto move", err)
			return err
		} else if move {
			return nil
		}
	}
	// 验证区域是否可用
	if err := logic.ValidPositions(position, build.FixRange); err != nil {
		fmt.Println("valid postion", err)
		return err
	}
	account := logic.GetDetailCache(logic, structure.NewBaseData(AccountType, id))
	if err := logic.Center.OnCreateBuild(id, account, buildId, info); err != nil {
		return err
	}
	attrId := utils.ToInt(params[0])
	instance := logic.createBuild(id, selfIdentity, info, buildId, 1, position, name, attrId, direction, mode)
	return instance.GetId()
}

func (logic *TypeMap) ResetNode(accountId int, selfIdentity int, key string, position []byte) interface{} {
	//fmt.Println("rest node", selfIdentity, key, position)
	nodeId := logic.Center.TargetIdMap[NodeType][key]

	instance := logic.resetNode(accountId, selfIdentity, nodeId, position)
	return instance.GetId()
}
func (logic *TypeMap) Update(accountId int, tt byte, dataId interface{}, scene string) interface{} {
	t := structure.PublicDataType(tt)
	result := logic.GetDetailCache(logic, structure.NewBaseData(t, dataId))

	if accountId > 0 && accountId != result.ToInt(AccountDataType) {
		fmt.Println("update accouount", accountId, result.ToInt(AccountDataType))
		return errors.New("账号不匹配")
	}
	key := result.ToString(Key)
	level := result.ToInt(Level)
	owner := logic.GetAbilityInstance(logic, result)
	// 主动设置更新呢
	owner.Change()
	effect := owner.Generate(logic, result, logic)

	fmt.Println("unit update effect", effect, "key", key)
	// 检查，并返回
	create := &UpdateTask{
		DataType: t,
		Id:       dataId,
		Position: result.ToBytes(Position),
		Key:      key,
		Identity: result.ToInt(Identity),
		Ability: &Ability{
			Level:         level,
			DirectAbility: effect.GetIds(model.DirectAbilityDefine),
			BuffAbility:   effect.GetIds(model.BuffAbilityDefine),
			AttrAbility:   effect.GetSlice(model.AttrAbilityDefine),
		},
		Scene: scene,
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(structure.NewBaseData(AccountType, accountId)).One(UpdateTaskEvent, create).Task(0, nil)
	return nil
}

func (logic *TypeMap) UseDirect(accountId int, selfIdentity int, tt byte, dataId interface{}, directId int, targetT byte, targetId interface{}, params []interface{}) interface{} {
	t := structure.PublicDataType(tt)
	baseData := structure.NewBaseData(t, dataId)
	direct := logic.Center.DirectMap[directId]

	if direct.Mode == model.MainDirectMode || direct.Mode == model.AutoDirectMode {
		return logic.Center.LanguageError("NOT_MANUAL_DIRECT")
	}

	instance := logic.GetDetailCache(logic, baseData)
	if accountId > 0 && accountId != utils.ToInt(instance.GetProp(AccountDataType)) {
		return errors.New("账号不匹配")
	}

	abilityProp := ReceiveAbilityProp(instance)
	coolTime := abilityProp.GetDirectCool(directId)
	if coolTime > logic.CurrentTime() {
		return logic.Center.LanguageError("WAIT_COOL_TIME")
	}

	var position []byte
	var currentPosition []byte
	var targetType structure.PublicDataType
	var targetData *structure.BaseData
	var target cooperate.PropsInstance
	var targetKey string
	var targetKeyId int
	if targetId != nil {
		targetType = structure.PublicDataType(targetT)
		targetData = structure.NewBaseData(targetType, targetId)
		target = logic.GetDetailCache(logic, targetData)
		if target == nil {
			return errors.New("目标错误")
		}
		targetKey = target.ToString(Key)
		targetKeyId = logic.Center.TargetIdMap[target.GetDataType()][targetKey]
		if targetType == NodeType {
			position = utils.ToBytes(targetId)
		}
		if position == nil || len(position) == 0 {
			position = target.ToBytes(Position)
		}
		currentPosition = instance.ToBytes(Position)

		if direct.Range > 0 && (direct.Mode == model.BuildDirectMode || direct.Mode == model.PlaceDirectMode) {
			// 验证区域是否可用
			if err := logic.ValidPositions(position, int(direct.Range)); err != nil {
				return err
			}
		}
		if direct.MaxDistance > 0 {
			if target.GetDataType() == UnitType {
				// 有距离要求，如果超过距离，则移动后执行
				// 如果无法执行，则停止移动
				if move, err := logic.autoMove(int(direct.MaxDistance), instance, direct.AutoMove, position, currentPosition, int(direct.Range), logic.MakeQuery(accountId, selfIdentity, UseDirect, []interface{}{tt, dataId, directId, targetT, targetId, params}, nil)); err != nil {
					return err
				} else if move {
					return nil
				}
			} else {
				return logic.Center.LanguageError("DISTANCE_MAX")
			}
		}
		if direct.Range > 0 && (direct.Mode == model.BuildDirectMode || direct.Mode == model.PlaceDirectMode) {
			// 验证区域是否可用
			if err := logic.ValidPositions(position, int(direct.Range)); err != nil {
				return err
			}
		}
	}

	if target != nil {
		if !direct.ValidTarget(target.GetDataType(), targetKeyId) {
			return errors.New("目标类型错误")
		}
		if direct.TargetMode == model.SelfTargetMode {
			if target.GetDataType() != instance.GetDataType() {
				return errors.New("目标错误")
			}
			if target.GetId() != instance.GetId() {
				return errors.New("目标错误")
			}
		} else if direct.TargetMode == model.RangeTargetMode {
			if targetType != NodeType {
				return errors.New("目标类型错误")
			}
		}
	} else {
		if !direct.ValidTarget(0, 0) {
			return errors.New("目标类型错误")
		}
		if direct.TargetMode != model.SelfTargetMode {
			return errors.New("目标错误")
		} else {
			target = instance
		}
	}

	if coolTime > logic.CurrentTime() {
		return logic.Center.LanguageError("WAIT_COOL_TIME")
	}
	doOperates, canDo := logic.setSustain(instance, direct, logic.CurrentTime())
	if !canDo {
		return errors.New("正在执行")
	}
	// 会执行消耗，所以下方只能是一些规则检查，提供完整性测试的
	if err := logic.Center.OnUseDirect(logic, accountId, selfIdentity, instance.Data(), direct); err != nil {
		return err
	}
	var logicInfo serialize.IStruct
	var operates []cooperate.UpdateOperateContent
	logicTime := logic.CurrentTime()
	switch direct.Mode {
	case model.ManualDirectMode:
		switch direct.ScheduleType {
		case MapManualLogicType:
			if target == nil {
				return logic.Center.LanguageError("NEED_TARGET")
			}
			if targetType != NodeType {
				return logic.Center.LanguageError("ERROR_TARGET")
			}
			// 驻守所选范围，如果有技能，先释放一次技能
			// 给节点范围添加buff
			buffId := utils.ToInt(params[1])
			positions := logic.RangeDistance(position, int(direct.Range-1))
			if buffId > 0 {
				// 延长持续时间
				attrId := utils.ToInt(params[2])

				targets := make([]cooperate.PropsInstance, len(positions))
				for index, position := range positions {
					targets[index] = logic.GetDetailCache(logic, structure.NewBaseData(NodeType, position))
				}

				logic.addBuff(buffId, instance, targets, logic.CurrentSecond(), attrId)
			}
			skillId := utils.ToInt(params[0])
			if skillId > 0 {
				if err := logic.attackByDirect(direct, instance, target); err != nil {
					return err
				}
			}
		case AttackLogicType:
			if target == nil {
				return logic.Center.LanguageError("NEED_TARGET")
			}
			skillId := utils.ToInt(params[0])
			if skillId > 0 {
				if err := logic.attackByDirect(direct, instance, target); err != nil {
					return err
				}
			}
		case SearchLogicType:
			// 探查
			search := &SearchLogic{
				Nodes: logic.RangeDistance(position, int(direct.Range)-1),
			}
			logic.Search(instance, search)
		case TauntLogicType:
			// 嘲讽
			taunt := &TauntLogic{
				Distance: int(direct.Range) - 1,
				Range:    DistanceTargetRange,
				Identity: EnemyTargetIdentity,
				LogicKey: "taunt",
			}
			logic.Taunt(instance, taunt)
		case RepairLogicType:
			if target == nil {
				return logic.Center.LanguageError("NEED_TARGET")
			}
			skillId := utils.ToInt(params[0])
			if skillId > 0 {
				// 修复
				items, _ := logic.GetFixedList([][]byte{position})
				if items[0] == nil {
					// 建筑不存在
					return errors.New("建筑不存在")
				}
				logicInfo = &RepairLogic{
					Target:    *targetData,
					DirectId:  directId,
					StartTime: logicTime,
				}
				logicTime += int64(direct.IntervalTime)
			}
		case SpeedTeleportLogicType:
			// 瞬移
			speedTeleport := &SpeedTeleportLogic{
				Target: position,
			}
			logic.SpeedTeleport(instance, speedTeleport)
		case SnipeLogicType:
			if target == nil {
				return logic.Center.LanguageError("NEED_TARGET")
			}
			if targetType == NodeType {
				return logic.Center.LanguageError("ERROR_TARGET")
			}
			visiable := TargetVisible(instance.ToByte(Visible))
			if visiable == NormalTargetVisible {
				return logic.Center.LanguageError("ERROR_VISIABLE")
			}
			skillId := utils.ToInt(params[0])
			if skillId > 0 {
				if err := logic.attackByDirect(direct, instance, target); err != nil {
					return err
				}
			}

			snipe := &SnipeLogic{
				Target: target.Data(),
			}
			logic.Snipe(instance, snipe)
		}
	case model.BuildDirectMode:
		if position == nil {
			return logic.Center.LanguageError("NEED_POSITION")
		}
		// buildKey, level, name
		buildId := utils.ToInt(params[0])
		level := utils.ToInt(params[1])
		name := utils.ToString(params[2])
		// 缩短建造时间
		attrId := utils.ToInt(params[3])
		direction := utils.ToBytes(params[4])
		mode := utils.ToInt(params[5])

		logic.createBuild(accountId, selfIdentity, instance, buildId, level, position, name, attrId, direction, mode)
	case model.PlaceDirectMode:
		if position == nil {
			return logic.Center.LanguageError("NEED_POSITION")
		}
		// itemId, name
		itemId := utils.ToInt(params[0])
		name := utils.ToString(params[1])
		logic.createItem(accountId, selfIdentity, itemId, position, name)
	case model.BuffDirectMode:
		buffId := utils.ToInt(params[0])
		attrId := utils.ToInt(params[1])
		var targets []cooperate.PropsInstance
		touchTargets, _ := logic.findTargetRange(instance, direct, target)
		if touchTargets == nil {
			targets = append(targets, target)
		} else {
			for _, t := range touchTargets {
				targets = append(targets, t)
			}
		}
		logic.addBuff(buffId, instance, targets, logic.CurrentSecond(), attrId)
	case model.GroupBuffDirectMode:
		buffId := utils.ToInt(params[0])
		// 新增的也要添加
		needNew := utils.ToBool(params[1])
		readyTime := utils.ToInt64(params[2])
		attrId := utils.ToInt(params[3])
		if needNew {
			validProp := instance.Timer().Prop(DirectValidPrefix, directId)
			operates = append(operates, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangeData,
				Key:     validProp,
				Value:   logic.CurrentTime(),
			})
		}
		buffInfo := NewBuffInfo(buffId, baseData.DataType, baseData.Id, 0)
		buffB, _ := buffInfo.MarshalMsg(nil)
		c := &cooperate.CustomScheduleContent{
			Type:  BatchUpdateCustomType,
			Logic: nil,
			Async: true,
		}
		buff := logic.Center.BuffMap[buffId]

		t, _ := logic.getChangeTime(attrId, instance, logic.CurrentSecond(), buff.SustainedTime)
		tt := &BatchOperateCustomLogic{
			DataType:   AccountType,
			TargetKey:  targetKey,
			TargetType: targetType,
			Operates: []cooperate.UpdateOperateContent{{
				Operate: cooperate.AddTimeSorted,
				Key:     string(BuffAbilityExtend),
				Index:   int(t),
				Value:   buffB,
			}},
		}
		if baseData.DataType == AccountType {
			tt.Ids = []interface{}{accountId}
		} else {
			// 其余都直接查询依赖Account，传递下去
			depend := logic.DefaultDepend(instance.GetDataType(), AccountDataType)
			if depend == nil {
				return nil
			}
			ids := instance.ListDepend(depend.Be)
			if ids == nil {
				return nil
			}
			tt.Ids = utils.ToInterfaceSlice(ids)
		}
		b, _ := tt.MarshalMsg(nil)
		c.Logic = b
		cb, _ := c.MarshalMsg(nil)
		builder := logic.ScheduleBuilder()
		builder.BindMapNoId(logic.GetMapNoId()).Key("buff"+utils.ToString(buffId)).Target(*baseData).Bind(cooperate.CustomSchedule, cb).Schedule(readyTime, nil, 0)
	}
	coolOperates := logic.addCoolTime(instance, direct)
	if coolOperates != nil {
		operates = append(operates, coolOperates...)
	}
	// 如果有持久化，则取消目标，取消任务
	if doOperates != nil {
		operates = append(operates, doOperates...)

		clearOperate := logic.clearTarget(instance)
		if clearOperate != nil {
			operates = append(operates, clearOperate...)
		}
	}
	if len(operates) > 0 {
		updateData := cooperate.OperateContent{
			MapNoId: logic.GetMapNoId(),
			Target:  baseData,
			Operates: []cooperate.OperateData{
				cooperate.NewOperateData(cooperate.BatchUpdateOperate, &cooperate.UpdateOperateData{
					Data:     *baseData,
					Operates: operates,
				}),
			},
		}
		logic.PushOperate(updateData, 0)
	}
	if logicInfo != nil {
		_ = logic.AddTouchSchedule(logic.GetMapNoId(), &cooperate.ScheduleContent{From: nil, Target: baseData, Key: direct.GetScheduleKey(), Time: logicTime}, 1, position, direct.ScheduleType, logicInfo, params)
	}
	return nil
}

func (logic *TypeMap) Upgrade(accountId int, tt byte, dataId interface{}, level int) interface{} {
	t := structure.PublicDataType(tt)
	result := logic.GetDetailCache(logic, structure.NewBaseData(t, dataId))
	//toolBox := utils.ToBytes(result[Toolbox])
	if accountId > 0 && accountId != result.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	key := result.ToString(Key)
	result.MergeProp(Level, level)
	owner := logic.GetAbilityInstance(logic, result)
	owner.Change()
	effect := owner.Generate(logic, result, logic)
	fmt.Println("upgrade", logic.GetMapNoId(), result.Data(), effect)
	// 检查，并返回
	create := &UpdateTask{
		DataType: t,
		Id:       dataId,
		Position: result.ToBytes(Position),
		Key:      key,
		Identity: result.ToInt(Identity),
		Ability: &Ability{
			Level:         level,
			DirectAbility: effect.GetIds(model.DirectAbilityDefine),
			BuffAbility:   effect.GetIds(model.BuffAbilityDefine),
			AttrAbility:   effect.GetSlice(model.AttrAbilityDefine),
		},
		Scene: "upgrade",
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(structure.NewBaseData(t, dataId)).One(UpdateTaskEvent, create).Task(0, nil)

	return nil
}

func (logic *TypeMap) MoveUnit(userUnitId string, moveMode byte, dataType byte, id interface{}, targetPositions [][]byte) interface{} {
	//fmt.Println("move unit", userUnitId, moveMode, dataType, id, targetPositions)
	if userUnitId == "" {
		return nil
	}
	unitData := structure.NewBaseData(UnitType, userUnitId)
	instance := logic.GetDetailCache(logic, unitData)
	if instance == nil {
		return errors.New("部队为空")
	}
	fmt.Println("move unit", instance.Data(), instance.ToString(Key), logic.Center.TargetIdMap[UnitType])
	unitId := logic.Center.TargetIdMap[UnitType][instance.ToString(Key)]
	unit := logic.Center.UnitMap[unitId]
	// [167 145]
	content := &cooperate.MoveScheduleContent{
		SelfMask:        unit.SelfMask,
		OtherMask:       unit.OtherMask,
		Type:            AttackLogicType,
		TargetPositions: targetPositions,
	}
	start := instance.ToBytes(Position)
	if start == nil || len(start) == 0 {
		return errors.New("部队还未部署")
	}
	//fmt.Println("start move", content)
	var position []byte
	switch moveMode {
	case NormalMoveMode:
		if dataType != byte(NodeType) && dataType != byte(BuildType) {
			return logic.Center.LanguageError("MOVE_NEED_POSITION")
		}
		position = utils.ToBytes(id)
		if targetPositions == nil && dataType == byte(BuildType) {
			target := structure.NewBaseData(structure.PublicDataType(dataType), id)
			targetInstance := logic.GetDetailCache(logic, target)
			targetPositions = logic.getPositions(targetInstance)
		}
		attackLogic := &AttackLogic{
			Follow:    false,
			CanAttack: false,
			Range:     DistanceTargetRange,
		}
		b, _ := attackLogic.MarshalMsg(nil)
		content.Logic = b
	case AutoAttackMoveMode:
		if dataType != byte(NodeType) {
			return logic.Center.LanguageError("MOVE_NEED_POSITION")
		}
		target := structure.NewBaseData(structure.PublicDataType(dataType), id)
		targetInstance := logic.GetDetailCache(logic, target)
		position = targetInstance.ToBytes(Position)
		content.OtherMask = unit.OtherAutoMask
		attackLogic := &AttackLogic{
			Follow:    true,
			CanAttack: true,
			Range:     DistanceTargetRange,
		}
		b, _ := attackLogic.MarshalMsg(nil)
		content.Logic = b
	case AttackTargetMode:
		target := structure.NewBaseData(structure.PublicDataType(dataType), id)
		targetInstance := logic.GetDetailCache(logic, target)
		position = targetInstance.ToBytes(Position)
		// todo 判断目标是否可攻击
		if !logic.IsTargetIdentity(instance.ToInt(Identity), targetInstance.ToInt(Identity), int(CanAttackTargetIdentity)) {
			return logic.Center.LanguageError("NO_CAN_ATTACK")
		}
		if targetPositions == nil {
			targetPositions = logic.getPositions(targetInstance)
		}
		fmt.Println("attack", position, targetInstance.Data())
		attackLogic := &AttackLogic{
			Follow:    true,
			CanAttack: false,
			Range:     DistanceTargetRange,
		}
		b, _ := attackLogic.MarshalMsg(nil)
		content.Logic = b
		content.Touch = &cooperate.TouchScheduleContent{Target: target}
	}
	plan, positions := logic.OnPlanFinding(start, position, &pathfinding.StrategyMask{
		Self:            content.SelfMask,
		Other:           content.OtherMask,
		Identity:        instance.ToInt(Identity),
		Filter:          nil,
		Pass:            nil,
		TargetPositions: targetPositions,
	}, true)
	//fmt.Println("move unit", unitData, position, plan, positions, targetPositions)
	if positions == nil || len(positions) == 0 {
		// 无有效路径
		switch moveMode {
		case NormalMoveMode:
			return errors.New("无可移动路径")
		case AutoAttackMoveMode:
			return errors.New("无可移动路径")
		case AttackTargetMode:
			return errors.New("无法攻击当前目标")
		}
	}
	var operates []cooperate.UpdateOperateContent

	if moveMode == NormalMoveMode {
		clearOperate := logic.clearTarget(instance)
		if clearOperate != nil {
			operates = append(operates, clearOperate...)
		}
	}
	doOperates, canDo := logic.setSustain(instance, nil, logic.CurrentTime())
	if !canDo {
		return errors.New("正在执行")
	}
	if doOperates != nil {
		operates = append(operates, doOperates...)
	}
	// 移动操作打断当前ready
	breakOperate, _ := logic.breakBehavior(instance, logic.CurrentTime())
	if breakOperate != nil {
		operates = append(operates, breakOperate...)
	}
	content.Plan = plan
	content.Positions = positions
	content.TargetPositions = targetPositions
	if moveMode != AttackTargetMode {
		content.LastPosition = plan[len(plan)-1]
	}

	logic.OnEvent(OnStartMoveEvent, []interface{}{instance, position, content})
	builder := logic.ScheduleBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).Target(*unitData).Key("move").
		Move(content).Schedule(0, nil, 0)

	if operates != nil {
		operateData := &cooperate.UpdateOperateData{
			Data:     *unitData,
			Operates: operates,
		}
		updateData := cooperate.OperateContent{
			MapNoId: logic.GetMapNoId(),
			Target:  &operateData.Data,
			Operates: []cooperate.OperateData{
				cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
			},
		}
		logic.PushOperate(updateData, 0)
	}
	return nil
}
func (logic *TypeMap) Destroy(accountId int, tt byte, dataId interface{}) interface{} {
	t := structure.PublicDataType(tt)
	result := logic.GetPropsCache(logic, structure.NewBaseData(t, dataId), []string{Key, Position, AccountDataType, Identity})
	//toolBox := utils.ToBytes(result[Toolbox])
	if result == nil {
		return errors.New("不存在")
	}
	if accountId > 0 && accountId != utils.ToInt(result[AccountDataType]) {
		return errors.New("账号不匹配")
	}

	// todo 销毁不是战斗销毁，是手动销毁，要清除所有数据
	destroy := &DestroyTask{
		DataType: t,
		Id:       dataId,
		Identity: utils.ToInt(result[Identity]),
		Key:      utils.ToString(result[Key]),
		Position: utils.ToBytes(result[Position]),
	}

	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).One(DestroyTaskEvent, destroy).Task(0, nil)
	return nil
}

func (logic *TypeMap) FlyUnit(accountId int, selfIdentity int, unitId string, position []byte, nextPosition []byte) interface{} {
	unitData := structure.NewBaseData(UnitType, unitId)
	instance := logic.GetDetailCache(logic, unitData)
	//toolBox := utils.ToBytes(result[Toolbox])
	if instance == nil {
		return errors.New("部队不存在")
	}
	if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	// 需要当前在传送点，目标也是传送点
	startBuild := logic.GetDetailCache(logic, structure.NewBaseData(BuildType, position))
	if startBuild == nil || startBuild.AttrWithId(logic.CanTeleportIn) == 0 {
		return errors.New("起点不是传送点")
	}
	endBuild := logic.GetDetailCache(logic, structure.NewBaseData(BuildType, position))
	if endBuild == nil || endBuild.AttrWithId(logic.CanTeleportIn) == 0 {
		return errors.New("目标不是传送点")
	}

	partner, _ := logic.JudgeIdentity(selfIdentity, endBuild.ToInt(Identity))
	if !partner {
		return errors.New("只能使用友方传送")
	}

	currentPosition := instance.ToBytes(Position)
	if move, err := logic.autoMove(1, instance, true, position, currentPosition, 1, logic.MakeQuery(accountId, selfIdentity, FlyUnit, []interface{}{unitId, position, nextPosition}, nil)); err != nil {
		fmt.Println("auto move", err)
		return err
	} else if move {
		return nil
	}
	logic.OnFly(unitData, position, nextPosition)
	return nil
}

func (logic *TypeMap) PutUnit(accountId int, selfIdentity int, unitIds []string, position []byte) interface{} {
	//fmt.Println("put unit", selfIdentity, unitId, position)
	fix := false
	var build *Build
	var nodeInstance cooperate.PropsInstance
	if position != nil && len(position) > 0 {
		// 判断投放点
		nodeInstance = logic.GetDetailCache(logic, structure.NewBaseData(NodeType, position))
		fmt.Println("put node", nodeInstance.Data(), nodeInstance.ToString(Key))
		if nodeInstance == nil || nodeInstance.ToString(Key) != "put" {
			buildInstance := logic.GetDetailCache(logic, structure.NewBaseData(BuildType, position))
			if buildInstance == nil {
				return errors.New("无可部署点")
			}
			fix = true
			build = buildInstance.(*Build)
		} else {
			success := nodeInstance.ToInt("putSuccessNumber")
			canNumber := nodeInstance.ToInt("putPlayerNumber")
			singleNumber := nodeInstance.ToInt("putUnitSingleNumber")
			fmt.Println("put node", success, canNumber, singleNumber)
			if singleNumber < len(unitIds) {
				return errors.New("投放点部队数超过")
			}
			if canNumber < success+len(unitIds) {
				return errors.New("投放点超过最大投放数")
			}
		}
	} else {
		// 获取随机投放点
		nodes := logic.ListDepend(logic, cooperate.ManageType, utils.ToString(selfIdentity)+"put", IK+NodeDataType)
		if nodes == nil || len(nodes) == 0 {
			return errors.New("无可投放点")
		}
		l := len(nodes)
		t := 3
		for {
			t -= 1
			if t == 0 {
				return errors.New("无可投放点")
			}
			r := rand.Int31n(int32(l))
			nodeInstance = nodes[r]
			fmt.Println("put key", logic.GetMapNoId(), nodeInstance.ToString(Key))
			//success := nodeInstance.ToInt("putSuccessNumber")
			//canNumber := nodeInstance.ToInt("putPlayerNumber")
			//singleNumber := nodeInstance.ToInt("putUnitSingleNumber")
			//if singleNumber < len(unitIds) {
			//	continue
			//}
			//if canNumber <= success {
			//	continue
			//}
			break
		}
	}
	instances := []cooperate.PropsInstance{}
	for _, unitId := range unitIds {
		unitData := structure.NewBaseData(UnitType, unitId)
		instance := logic.GetDetailCache(logic, unitData)
		if instance == nil {
			return errors.New("部队不存在" + "putunit" + utils.ToString(unitData.Id))
		}
		//fmt.Println("account", id, instance.ToInt(AccountDataType))
		if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
			fmt.Println("put unit", accountId, instance)
			return errors.New("账号不匹配")
		}
		instances = append(instances, instance)
	}
	var positions [][]byte
	if !fix {
		nodeId := logic.Center.TargetIdMap[NodeType][nodeInstance.ToString(Key)]
		node := logic.Center.NodeMap[nodeId]

		fmt.Println("put unit node", logic.GetMapNoId(), nodeInstance, nodeInstance.ToString(Key), nodeId, nodeInstance.ToBytes(Position), unitIds, instances, position)
		position = nodeInstance.ToBytes(Position)
		requests := []serialize.AutoIStruct{}
		for _, instance := range instances {
			fmt.Println("put unit", logic.GetMapNoId(), instance, instance.ToString(Key))
			unitId := logic.Center.TargetIdMap[UnitType][instance.ToString(Key)]
			unit := logic.Center.UnitMap[unitId]

			request := &pathfinding.StrategyBlockRequest{
				Item:     instance.GetItem(),
				Position: position,
				PreSeat:  true,
				Mask: &pathfinding.StrategyMask{
					Self:     unit.SelfMask,
					Other:    unit.OtherMask,
					Identity: selfIdentity,
				},
			}
			requests = append(requests, request)
		}
		positions = logic.CanAndPreRange(position, node.LogicRange, logic.CurrentTime(), requests)
		position = positions[0]
	}

	var operateList [][]cooperate.UpdateOperateContent
	if fix {
		for i := 0; i < len(unitIds); i++ {
			var operates []cooperate.UpdateOperateContent
			operates = append(operates, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangePosition,
				Value:   position,
			}, cooperate.UpdateOperateContent{
				Operate: cooperate.AddDepend,
				Index:   int(BuildType),
				Value:   build.GetId(),
				Key:     BuildDataType,
			}, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangeIgnore,
				Value:   true,
			}, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangeData,
				Key:     UnitStatus,
				Value: &cooperate.Sustain{
					Type:     model.UnitInBattle,
					Params:   nil,
					Start:    logic.CurrentTime(),
					Time:     0,
					CanBreak: true,
				},
			})
			operateList = append(operateList, operates)
		}
	} else {
		for i := 0; i < len(unitIds); i++ {
			instance := instances[i]
			var operates []cooperate.UpdateOperateContent
			operates = append(operates, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangePosition,
				Value:   positions[i],
			}, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangeIgnore,
				Value:   false,
			}, cooperate.UpdateOperateContent{
				Operate: cooperate.ChangeData,
				Key:     UnitStatus,
				Value: &cooperate.Sustain{
					Type:     model.UnitInBattle,
					Params:   nil,
					Start:    logic.CurrentTime(),
					Time:     0,
					CanBreak: true,
				},
			})
			operateList = append(operateList, operates)

			logic.setBlock(instance, nil, position, nil, logic.CurrentTime(), 0, selfIdentity, NormalTargetVisible)
		}
	}

	if operateList != nil {
		for index, instance := range instances {
			operateData := &cooperate.UpdateOperateData{
				Data:     *instance.Data(),
				Operates: operateList[index],
			}
			//updateData := cooperate.OperateContent{
			//	MapNoId: logic.GetMapNoId(),
			//	Target:  &operateData.Data,
			//	Operates: []cooperate.OperateData{
			//		cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
			//	},
			//}
			//logic.PushOperate(updateData, 100)

			//fmt.Println("move", info.Target, index, len(content.Positions), content.PlanIndex, len(content.Plan), info.Time, positions, plan)
			extend := cooperate.NewModeExtend([]interface{}{}, logic.GetMapNoId(), nil, position)
			extend.UpdateOperate = operateData
			logic.Mode(logic, instance, instance, *logic.Event.PutUnit, 0, extend)
		}
		if nodeInstance != nil {
			success := nodeInstance.ToInt("putSuccessNumber")
			canNumber := nodeInstance.ToInt("putPlayerNumber")
			if success+len(unitIds) >= canNumber {
				destroy := &DestroyTask{
					DataType: nodeInstance.GetDataType(),
					Id:       nodeInstance.GetId(),
					Identity: nodeInstance.ToInt(Identity),
					Key:      nodeInstance.ToString(Key),
					Position: position,
				}
				builder := logic.TaskBuilder()
				builder.BindMapNoId(logic.GetMapNoId()).One(DestroyTaskEvent, destroy).Task(0, nil)
			} else {
				operateData := &cooperate.UpdateOperateData{
					Data: *nodeInstance.Data(),
					Operates: []cooperate.UpdateOperateContent{{
						Operate: cooperate.IncrDataSync,
						Key:     "putSuccessNumber",
						Value:   len(unitIds),
					}},
				}
				updateData := cooperate.OperateContent{
					MapNoId: logic.GetMapNoId(),
					Target:  nodeInstance.Data(),
					Operates: []cooperate.OperateData{
						cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
					},
				}
				logic.PushOperate(updateData, 0)
			}
		}
	}
	return position
}

func (logic *TypeMap) DownUnit(accountId int, selfIdentity int, unitIds []string) interface{} {
	//fmt.Println("down unit", selfIdentity, unitId, position)
	instances := []cooperate.PropsInstance{}
	for _, unitId := range unitIds {
		unitData := structure.NewBaseData(UnitType, unitId)
		instance := logic.GetDetailCache(logic, unitData)
		if instance == nil {
			return errors.New("部队不存在" + "downunit" + utils.ToString(unitId))
		}
		fmt.Println("account", accountId, instance.ToInt(AccountDataType))
		if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
			//fmt.Println("put unit", id, instance.ToInt(AccountDataType))
			return errors.New("账号不匹配")
		}
		if instance.ToBool(Combat) {
			return errors.New("战斗中无法撤退")
		}
		instances = append(instances, instance)
	}
	var operateList [][]cooperate.UpdateOperateContent
	for i := 0; i < len(unitIds); i++ {
		instance := instances[i]
		var operates []cooperate.UpdateOperateContent
		operates = append(operates, cooperate.UpdateOperateContent{
			Operate: cooperate.ChangePosition,
			Value:   nil,
		}, cooperate.UpdateOperateContent{
			Operate: cooperate.ChangeIgnore,
			Value:   true,
		}, cooperate.UpdateOperateContent{
			Operate: cooperate.ChangeData,
			Key:     UnitStatus,
			Value: &cooperate.Sustain{
				Type:     model.UnitInFree,
				Params:   nil,
				Start:    logic.CurrentTime(),
				Time:     0,
				CanBreak: true,
			},
		})
		ab := ReceiveAbilityProp(instance)
		if ab != nil {
			a := ab.ClearBuff()
			if len(a) > 0 {
				operates = append(operates, a...)
			}
		}
		operateList = append(operateList, operates)

		logic.MoveSeat(instance.GetItem(), instance.ToBytes(Position), nil, logic.CurrentTime(), 0, 0, nil)
	}

	if operateList != nil {
		for index, instance := range instances {
			operateData := &cooperate.UpdateOperateData{
				Data:     *instance.Data(),
				Operates: operateList[index],
			}
			//updateData := cooperate.OperateContent{
			//	MapNoId: logic.GetMapNoId(),
			//	Target:  &operateData.Data,
			//	Operates: []cooperate.OperateData{
			//		cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
			//	},
			//}
			extend := cooperate.NewModeExtend([]interface{}{}, logic.GetMapNoId(), nil, instance.ToBytes(Position))
			extend.UpdateOperate = operateData
			logic.Mode(logic, instance, instance, *logic.Event.DownUnit, 0, extend)
		}

	}
	return nil
}
func (logic *TypeMap) ChangeTargetMode(accountId int, unitId string, targetMode TargetModeDefine) interface{} {
	unitData := structure.NewBaseData(UnitType, unitId)
	instance := logic.GetDetailCache(logic, unitData)
	if instance == nil {
		return errors.New("部队不存在")
	}
	if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	var operates []cooperate.UpdateOperateContent
	operates = append(operates, cooperate.UpdateOperateContent{
		Operate: cooperate.ChangeData,
		Key:     TargetMode,
		Value:   targetMode,
	})
	operateData := &cooperate.UpdateOperateData{
		Data:     *unitData,
		Operates: operates,
	}
	updateData := cooperate.OperateContent{
		MapNoId: logic.GetMapNoId(),
		Target:  &operateData.Data,
		Operates: []cooperate.OperateData{
			cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
		},
	}
	// 不做传送事件
	logic.PushOperate(updateData, 100)
	return nil
}
func (logic *TypeMap) ChangeAiMode(accountId int, unitId string, aiMode AiModeDefine) interface{} {
	unitData := structure.NewBaseData(UnitType, unitId)
	instance := logic.GetDetailCache(logic, unitData)
	if instance == nil {
		return errors.New("部队不存在")
	}
	if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	var operates []cooperate.UpdateOperateContent
	operates = append(operates, cooperate.UpdateOperateContent{
		Operate: cooperate.ChangeData,
		Key:     AiMode,
		Value:   aiMode,
	})
	operateData := &cooperate.UpdateOperateData{
		Data:     *unitData,
		Operates: operates,
	}
	updateData := cooperate.OperateContent{
		MapNoId: logic.GetMapNoId(),
		Target:  &operateData.Data,
		Operates: []cooperate.OperateData{
			cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
		},
	}
	// 不做传送事件
	logic.PushOperate(updateData, 0)
	return nil
}
func (logic *TypeMap) ChangeBehaviorPattern(accountId int, unitId string, behaviorPattern int) interface{} {
	unitData := structure.NewBaseData(UnitType, unitId)
	instance := logic.GetDetailCache(logic, unitData)
	if instance == nil {
		return errors.New("部队不存在" + "behaviorPattern" + utils.ToString(unitId))
	}
	if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	var operates []cooperate.UpdateOperateContent
	operates = append(operates, cooperate.UpdateOperateContent{
		Operate: cooperate.ChangeData,
		Key:     BehaviorPattern,
		Value:   behaviorPattern,
	})
	operateData := &cooperate.UpdateOperateData{
		Data:     *unitData,
		Operates: operates,
	}
	updateData := cooperate.OperateContent{
		MapNoId: logic.GetMapNoId(),
		Target:  &operateData.Data,
		Operates: []cooperate.OperateData{
			cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
		},
	}
	// 不做传送事件
	logic.PushOperate(updateData, 0)
	return nil
}
func (logic *TypeMap) RobotUnit(accountId int, selfIdentity int, unitId string, position []byte, flag bool) interface{} {
	unitData := structure.NewBaseData(UnitType, unitId)
	instance := logic.GetDetailCache(logic, unitData)
	if instance == nil {
		return errors.New("部队不存在")
	}
	if accountId > 0 && accountId != instance.ToInt(AccountDataType) {
		return errors.New("账号不匹配")
	}
	fortress := logic.GetDetailCache(logic, structure.NewBaseData(FortressType, position))
	if fortress == nil {
		return errors.New("无法托管")
	}
	//fmt.Println("auto move")
	var operates []cooperate.UpdateOperateContent
	clearOperate := logic.clearTarget(instance)
	if clearOperate != nil {
		operates = append(operates, clearOperate...)
	}
	if flag {
		currentPosition := instance.ToBytes(Position)
		if move, err := logic.autoMove(1, instance, true, position, currentPosition, 1, logic.MakeQuery(accountId, selfIdentity, RobotUnit, []interface{}{unitId, position, flag}, nil)); err != nil {
			fmt.Println("auto move", err)
			return err
		} else if move {
			return nil
		}

		operates = append(operates, cooperate.UpdateOperateContent{
			Operate: cooperate.AddDepend,
			Index:   int(FortressType),
			Value:   position,
			Key:     FortressDataType,
		})
	} else {
		// 判断是否在托管状态
		operates = append(operates, cooperate.UpdateOperateContent{
			Operate: cooperate.RemoveDepend,
			Index:   int(FortressType),
			Value:   position,
			Key:     FortressDataType,
		})
	}

	if operates != nil {
		operateData := &cooperate.UpdateOperateData{
			Data:     *unitData,
			Operates: operates,
		}
		updateData := cooperate.OperateContent{
			MapNoId: logic.GetMapNoId(),
			Target:  &operateData.Data,
			Operates: []cooperate.OperateData{
				cooperate.NewOperateData(cooperate.BatchUpdateOperate, operateData),
			},
		}
		logic.PushOperate(updateData, 0)
	}
	return nil
}
func (logic *TypeMap) DependUpdate(t byte, id interface{}, targetTypes []byte, targetKeys [][]string, scene string) interface{} {
	baseData := structure.NewBaseData(structure.PublicDataType(t), id)
	info := logic.GetDetailCache(logic, baseData)
	c := &cooperate.CustomScheduleContent{
		Type:  BatchUpdateCustomType,
		Logic: nil,
		Async: true,
	}
	targetDepends := []string{}
	fd := logic.GetFieldsDefine(baseData.DataType)
	for _, beDepend := range fd.BeDepends {
		for _, ttt := range targetTypes {
			t := structure.PublicDataType(ttt)
			if t != beDepend.DependType {
				continue
			}
			targetDepends = append(targetDepends, beDepend.BeDepend)
		}
	}

	tt := &BatchUpdateCustomLogic{
		DataType:      AccountType,
		TargetDepends: targetDepends,
		TargetKeys:    targetKeys,
		Scene:         scene,
	}
	if baseData.DataType == AccountType {
		tt.Ids = []interface{}{id}
	} else {
		// 其余都直接查询依赖Account，传递下去
		depend := logic.DefaultDepend(info.GetDataType(), AccountDataType)
		if depend == nil {
			return nil
		}
		ids := info.ListDepend(depend.Be)
		if ids == nil {
			return nil
		}
		tt.Ids = utils.ToInterfaceSlice(ids)
	}
	b, _ := tt.MarshalMsg(nil)
	c.Logic = b
	cb, _ := c.MarshalMsg(nil)
	builder := logic.ScheduleBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).Key("update"+scene).Target(*baseData).Bind(cooperate.CustomSchedule, cb).Schedule(0, nil, 0)

	return nil
}

func (logic *TypeMap) GetRandomPosition(selfIdentity int, canType int, canFix bool, canSeat bool) interface{} {
	position := logic.RandomPosition(canType, canFix, canSeat, logic.CurrentTime())
	return position
}

func (logic *TypeMap) directValidProcess(accountId int, target cooperate.PropsInstance) {
	if accountId == 0 {
		return
	}
	// 分析directValid，添加有效指令
	account := logic.GetDetailCache(logic, structure.NewBaseData(AccountType, accountId))
	if account == nil {
		return
	}
	abilityProp := ReceiveAbilityProp(account)
	//fmt.Println("direct valid process", account, abilityProp, account, accountId)
	directValidMap := account.Timer().Values(DirectValidPrefix, account, abilityProp.DirectIds)
	for directId, valid := range directValidMap {
		direct := logic.Center.DirectMap[directId]
		if direct.Mode != model.GroupBuffDirectMode {
			continue
		}
		key := target.ToString(Key)
		targetKeyId := logic.Center.TargetIdMap[target.GetDataType()][key]
		if !direct.ValidTarget(target.GetDataType(), targetKeyId) {
			continue
		}
		buffId := utils.ToInt(direct.Params[0])
		// 新增的也要添加
		needNew := utils.ToBool(direct.Params[1])
		if !needNew {
			continue
		}
		logic.addBuff(buffId, account, []cooperate.PropsInstance{target}, int(valid/1000), utils.ToInt(direct.Params[3]))
	}
}

func (logic *TypeMap) getChangeTime(attrId int, from cooperate.PropsInstance, valid int, tt int) (int, bool) {

	if attrId > 0 {
		abilityProp := ReceiveAbilityProp(from)
		attrValue := abilityProp.GetAttrWithId(attrId)
		valid += attrValue
	}
	if tt+valid < logic.CurrentSecond() {
		return 0, false
	}
	t := tt + valid
	return t, true
}

func (logic *TypeMap) addBuff(buffId int, from cooperate.PropsInstance, targets []cooperate.PropsInstance, valid int, attrId int) bool {
	buff := logic.Center.BuffMap[buffId]

	t, ok := logic.getChangeTime(attrId, from, valid, buff.SustainedTime)
	if !ok {
		return false
	}
	buffInfo := NewBuffInfo(buffId, from.GetDataType(), from.GetId(), 0)
	buffB, err := buffInfo.MarshalMsg(nil)
	if err != nil {
		fmt.Println("add buff", err)
	} else {
		fmt.Println("add buff", buffB)
	}
	operates := make([]cooperate.OperateData, len(targets))
	for index, target := range targets {
		operates[index] = cooperate.NewOperateData(cooperate.BatchUpdateOperate, &cooperate.UpdateOperateData{
			Data: *target.Data(),
			Operates: []cooperate.UpdateOperateContent{{
				Operate: cooperate.AddTimeSorted,
				Key:     string(BuffAbilityExtend),
				Index:   t,
				Value:   buffB,
			}},
		})
	}
	// 提交buff信息
	updateData := cooperate.OperateContent{
		MapNoId:  logic.GetMapNoId(),
		Target:   targets[0].Data(),
		Operates: operates,
	}
	logic.PushOperate(updateData, 0)
	return true
}

func (logic *TypeMap) autoMove(maxDistance int, instance cooperate.PropsInstance, autoMove bool, position []byte, currentPosition []byte, r int, query structure.EventData) (bool, error) {
	if _, canDo := logic.setSustain(instance, nil, logic.CurrentTime()); !canDo {
		return false, errors.New("正在执行")
	}
	if _, noBreak := logic.breakBehavior(instance, logic.CurrentTime()); !noBreak {
		return false, errors.New("正在执行")
	}
	distance := logic.Distance(position, currentPosition) - (int(r) - 1)
	if distance > int(maxDistance) {
		if autoMove {
			e := logic.GetEventCache(logic, instance, ArriveInlineEvent)
			if e != nil {
				// 已经是移动后访问，不继续移动
				return true, nil
			}
			// 移动
			res := logic.MoveUnit(utils.ToString(instance.GetId()), NormalMoveMode, byte(NodeType), position, logic.RangeDistance(position, int(r-1)))
			a, ok := res.(error)
			if ok {
				return false, a
			}
			baseData := instance.Data()
			operates := []cooperate.UpdateOperateContent{}
			// 添加到达事件
			operates = append(operates, cooperate.UpdateOperateContent{
				Operate: cooperate.BindEvent,
				Key:     utils.ToString(query.Content),
				Index:   int(query.Mode),
				Value:   ArriveInlineEvent,
			})
			updateData := cooperate.OperateContent{
				MapNoId: logic.GetMapNoId(),
				Target:  instance.Data(),
				Operates: []cooperate.OperateData{
					cooperate.NewOperateData(cooperate.BatchUpdateOperate, &cooperate.UpdateOperateData{
						Data:     *baseData,
						Operates: operates,
					}),
				},
			}
			logic.PushOperate(updateData, 0)
			fmt.Println("auto move start")
			return true, nil
		} else {
			return false, logic.Center.LanguageError("DISTANCE_MAX")
		}
	}
	return false, nil
}
func (logic *TypeMap) ValidPositions(position []byte, r int) error {
	// 验证区域是否可用
	_, items, _ := logic.GetItemList(logic.RangeDistance(position, int(r-1)), logic.CurrentTime())
	// 判断
	for _, item := range items {
		if item == nil {
			continue
		}
		r := structure.NewBaseDataByte(item)
		if r.DataType == UnitType {
			return logic.Center.LanguageError("EXIST_UNIT")
		}
		if r.DataType == BuildType {
			return logic.Center.LanguageError("EXIST_BUILD")
		}
		if r.DataType == ItemType {
			return logic.Center.LanguageError("EXIST_ITEM")
		}
	}
	return nil
}

func (logic *TypeMap) attackByDirect(direct *model.Direct, info cooperate.PropsInstance, target cooperate.PropsInstance) error {
	// 直接执行executeAttack逻辑
	//fmt.Println("attack", baseData, targetData, direct.Id)
	currentPosition := info.ToBytes(Position)
	self, _ := logic.getTouchInfo(info, 0)
	targets, positions := logic.findTargetRange(self, direct, target)
	if targets == nil {
		tt, _ := logic.getTouchInfo(target, logic.getDistance(target, currentPosition))
		targets = append(targets, tt)
	}
	//fmt.Println("target", targets)
	behavior := &Behavior{
		Id:       direct.Id,
		NeedCool: false,
	}
	behavior.Bind(direct)
	targetMode := TargetModeDefine(info.ToByte(TargetMode))
	selectTargets := logic.attackTarget(targetMode, behavior, self, targets, targets[0], nil)
	if selectTargets == nil || len(selectTargets) == 0 {
		if target.GetDataType() != NodeType {
			return logic.Center.LanguageError("NO_TARGET")
		}
	}
	logic.readyBehavior(self, behavior, logic.CurrentTime(), selectTargets, currentPosition)
	logic.executeAttack(self, self, selectTargets, positions, direct.Id, logic.CurrentTime(), currentPosition)
	return nil
}

func (logic *TypeMap) createBuild(accountId int, identity int, creater cooperate.PropsInstance, id int, level int, position []byte, name string, attrId int, direction []byte, mode int) cooperate.PropsInstance {
	build := logic.Center.BuildMap[id]
	result := structure.NewBaseData(BuildType, position)
	fd := logic.GetFieldsDefine(BuildType)
	instance := cooperate.NewPropInstance(logic, fd, result, map[string]interface{}{
		// 各个依赖项
		AccountDataType: accountId,
		Level:           level,
		Key:             build.Key,
	})
	logic.directValidProcess(id, instance)
	owner := cooperate.NewAbilityOwner()

	effect := owner.Generate(logic, instance, logic)
	if name == "" {
		name = build.Name
	}
	abilityProp := ReceiveAbilityProp(creater)
	attrValue := abilityProp.GetAttrWithId(attrId)
	depends := []*cooperate.DependentItem{}
	if id > 0 {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AccountDataType,
			Depend: structure.NewBaseData(AccountType, accountId),
		})
	} else if creater.GetDataType() == FortressType {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AiFortress,
			Depend: creater.Data(),
		})
	} else {
		if identity > 0 {
			depends = append(depends, &cooperate.DependentItem{
				Key:    AiForce,
				Depend: structure.NewBaseData(cooperate.ForceType, identity),
			})
		}

	}

	if build.NeedManage {
		depends = append(depends, &cooperate.DependentItem{
			Key:    cooperate.ManageDataType,
			Depend: structure.NewBaseData(cooperate.ManageType, BuildType),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IdentityManage,
			Depend: structure.NewBaseData(cooperate.ManageType, identity),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    KeyManage,
			Depend: structure.NewBaseData(cooperate.ManageType, build.Key),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IKManage,
			Depend: structure.NewBaseData(cooperate.ManageType, utils.ToString(identity)+build.Key),
		})
	}
	//	// 检查，并返回
	create := &CreateTask{
		DataType: BuildType,
		Id:       position,
		Position: position,
		Key:      build.Key,
		Identity: identity,
		Ability: &Ability{
			Level:         level,
			DirectAbility: effect.GetIds(model.DirectAbilityDefine),
			BuffAbility:   effect.GetIds(model.BuffAbilityDefine),
			AttrAbility:   effect.GetSlice(model.AttrAbilityDefine),
		},
		Depends: depends,
		Name:    name,
		Params:  []interface{}{"buildTime", attrValue * 1000, "direction", direction, "buildMode", mode},
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(result).One(CreateTaskEvent, create).Task(0, nil)
	return instance
}

func (logic *TypeMap) createItem(accountId int, identity int, id int, position []byte, name string) cooperate.PropsInstance {
	item := logic.Center.ItemMap[id]
	newId := logic.IncrTypeId(logic.GetMapNoId(), ItemType)
	result := structure.NewBaseData(ItemType, newId)
	fd := logic.GetFieldsDefine(ItemType)
	instance := cooperate.NewPropInstance(logic, fd, result, map[string]interface{}{
		// 各个依赖项
		AccountDataType: accountId,
		Key:             item.Key,
		Level:           1,
	})
	logic.directValidProcess(accountId, instance)
	owner := cooperate.NewAbilityOwner()
	effect := owner.Generate(logic, instance, logic)
	if name == "" {
		name = item.Name
	}
	depends := []*cooperate.DependentItem{}
	if id > 0 {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AccountDataType,
			Depend: structure.NewBaseData(AccountType, id),
		})
	}
	if item.NeedManage {
		depends = append(depends, &cooperate.DependentItem{
			Key:    cooperate.ManageDataType,
			Depend: structure.NewBaseData(cooperate.ManageType, ItemType),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IdentityManage,
			Depend: structure.NewBaseData(cooperate.ManageType, identity),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    KeyManage,
			Depend: structure.NewBaseData(cooperate.ManageType, item.Key),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IKManage,
			Depend: structure.NewBaseData(cooperate.ManageType, utils.ToString(identity)+item.Key),
		})
	}
	//	// 检查，并返回
	create := &CreateTask{
		DataType: ItemType,
		Id:       newId,
		Position: position,
		Key:      item.Key,
		Identity: identity,
		Ability: &Ability{
			Level:         0,
			DirectAbility: effect.GetIds(model.DirectAbilityDefine),
			BuffAbility:   effect.GetIds(model.BuffAbilityDefine),
			AttrAbility:   effect.GetSlice(model.AttrAbilityDefine),
		},
		Depends: depends,
		Name:    name,
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(result).One(CreateTaskEvent, create).Task(0, nil)
	return instance
}

func (logic *TypeMap) resetNode(accountId int, identity int, id int, position []byte) cooperate.PropsInstance {
	node := logic.Center.NodeMap[id]
	result := structure.NewBaseData(NodeType, position)
	fd := logic.GetFieldsDefine(NodeType)
	instance := cooperate.NewPropInstance(logic, fd, result, map[string]interface{}{
		// 各个依赖项
		AccountDataType: accountId,
		Key:             node.Key,
	})
	depends := []*cooperate.DependentItem{}
	if accountId > 0 {
		depends = append(depends, &cooperate.DependentItem{
			Key:    AccountDataType,
			Depend: structure.NewBaseData(AccountType, accountId),
		})
	} else {
		if identity > 0 {
			depends = append(depends, &cooperate.DependentItem{
				Key:    ForceDataType,
				Depend: structure.NewBaseData(cooperate.ForceType, identity),
			})
		}
	}

	if node.NeedManage {
		depends = append(depends, &cooperate.DependentItem{
			Key:    cooperate.ManageDataType,
			Depend: structure.NewBaseData(cooperate.ManageType, NodeType),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IdentityManage,
			Depend: structure.NewBaseData(cooperate.ManageType, identity),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    KeyManage,
			Depend: structure.NewBaseData(cooperate.ManageType, node.Key),
		})
		depends = append(depends, &cooperate.DependentItem{
			Key:    IKManage,
			Depend: structure.NewBaseData(cooperate.ManageType, utils.ToString(identity)+node.Key),
		})
	}
	//	// 检查，并返回
	create := &CreateTask{
		DataType: NodeType,
		Id:       position,
		Position: position,
		Key:      node.Key,
		Identity: identity,
		Depends:  depends,
	}
	builder := logic.TaskBuilder()
	builder.BindMapNoId(logic.GetMapNoId()).From(result).One(CreateTaskEvent, create).Task(0, nil)
	return instance
}

func (logic *TypeMap) clearTarget(instance cooperate.PropsInstance) []cooperate.UpdateOperateContent {
	// 在部队进行
	propInstance := instance.Receive(BattlePropType)
	if propInstance == nil {
		return nil
	}
	battle := propInstance.(*BattleProp)
	if battle.AttackTarget == nil {
		return nil
	}
	operates := []cooperate.UpdateOperateContent{
		{Operate: cooperate.ChangeData,
			Key:   AttackTarget,
			Value: nil,
		},
	}
	return operates
}

func (logic *TypeMap) addTarget(instance cooperate.PropsInstance, target *cooperate.TouchTarget) []cooperate.UpdateOperateContent {
	// 在部队进行消失或者主动操作是执行
	propInstance := instance.Receive(BattlePropType)
	if propInstance == nil {
		return nil
	}
	battle := propInstance.(*BattleProp)
	if battle.AttackTarget != nil && target.Equals(battle.AttackTarget) {
		return nil
	}
	var operates []cooperate.UpdateOperateContent
	// 新的攻击目标
	operates = append(operates, cooperate.UpdateOperateContent{
		Operate: cooperate.ChangeData,
		Key:     AttackTarget,
		Value:   target.Value(),
	})
	return operates
}

func (logic *TypeMap) addCoolTime(instance cooperate.PropsInstance, direct *model.Direct) []cooperate.UpdateOperateContent {
	if direct.CoolTime > 0 {
		coolProp := instance.Timer().Prop(DirectCoolPrefix, direct.Id)
		operates := []cooperate.UpdateOperateContent{{
			Operate: cooperate.ChangeData,
			Key:     coolProp,
			Value:   logic.CurrentTime() + int64(direct.CoolTime),
		}}
		return operates
	}
	return nil
}

func (logic *TypeMap) readyBehavior(instance cooperate.PropsInstance, behavior *Behavior, readyTime int64, selectTargets []*cooperate.TouchTarget, position []byte) bool {
	// 附加攻击忽略准备时间
	//fmt.Println("logic ready", instance.Data(), behavior.ReadyTime, logic.Event.ReadyBehavior)
	if behavior.ReadyTime > 0 {
		var readyOperates []cooperate.UpdateOperateContent
		readyOperates = append(readyOperates, cooperate.UpdateOperateContent{
			Operate: cooperate.ChangeData,
			Key:     ReadyBehaviorSustain,
			Value: &cooperate.Sustain{
				Type:     behavior.Id,
				Params:   []interface{}{behavior.GetSkillId()},
				Start:    readyTime,
				Time:     readyTime + int64(behavior.ReadyTime),
				CanBreak: true,
				Schedule: "",
			},
		})
		// 设定准备时间
		operateData := &cooperate.UpdateOperateData{
			Data:     *instance.Data(),
			Operates: readyOperates,
		}
		extend := cooperate.NewModeExtend([]interface{}{behavior.GetSkillId()}, logic.GetMapNoId(), nil, position)
		extend.UpdateOperate = operateData
		targets := make([]*structure.BaseData, len(selectTargets))
		for index, target := range selectTargets {
			targets[index] = target.Data()
		}
		extend.Content = &ReadyMessage{
			Center:  position,
			SkillId: behavior.GetSkillId(),
			Targets: targets,
		}
		logic.Mode(logic, instance, instance, *logic.Event.ReadyBehavior, readyTime, extend)
		return true
	}
	return false
}

func (logic *TypeMap) breakBehavior(instance cooperate.PropsInstance, breakTime int64) ([]cooperate.UpdateOperateContent, bool) {
	ready := instance.GetProp(ReadyBehaviorSustain)
	if ready == nil {
		return nil, true
	}
	readySustain := cooperate.NewSustainBy(ready)
	fmt.Println("braek behavior", readySustain.Time, breakTime)
	if readySustain.Time > breakTime {
		// 准备时间大于当前时间，则被打断
		// 附加攻击不会产生准备时间
		// 如果有准备，会打断的主要是用户操作了
		position := instance.ToBytes(Position)
		extend := cooperate.NewModeExtend(readySustain.Params, logic.GetMapNoId(), nil, position)
		logic.Mode(logic, nil, instance.Data(), *logic.Event.BreakBehavior, breakTime, extend)
		fmt.Println("send break behavior")
		operates := []cooperate.UpdateOperateContent{{
			Operate: cooperate.ChangeData,
			Key:     ReadyBehaviorSustain,
			Value:   nil,
		}}
		return operates, false
	}
	return nil, true
}

func (logic *TypeMap) setSustain(instance cooperate.PropsInstance, direct *model.Direct, breakTime int64) ([]cooperate.UpdateOperateContent, bool) {
	mapProp := instance.Receive(MapPropType)
	if mapProp == nil {
		return nil, true
	}
	canDo := false
	removeSchedule := ""
	var operates []cooperate.UpdateOperateContent
	doSustain := mapProp.(*MapProp).DoSustain
	if doSustain == nil {
		canDo = true
	} else if doSustain.Time < breakTime {
		canDo = true
	} else if doSustain.CanBreak {
		canDo = true
		removeSchedule = doSustain.Schedule
	}
	if canDo {
		if direct != nil {
			// todo 是否要区分准备时间，或者持续操作不会统准备一起
			if (direct.SustainedTime > 0 || direct.ReadyTime > 0) && direct.SustainSetting != nil {
				operates = append(operates, cooperate.UpdateOperateContent{
					Operate: cooperate.ChangeData,
					Key:     DoSustain,
					Value: &cooperate.Sustain{
						Type:     direct.SustainSetting.Type,
						Params:   direct.SustainSetting.Params,
						Start:    breakTime,
						Time:     breakTime + int64(direct.SustainedTime) + int64(direct.ReadyTime),
						CanBreak: direct.SustainSetting.CanBreak,
						Schedule: direct.GetScheduleKey(),
					},
				})
				if removeSchedule != "" {
					operates = append(operates, cooperate.UpdateOperateContent{
						Operate: cooperate.RemoveSchedule,
						Key:     removeSchedule,
					})
				}
			}
		}

	}
	return operates, canDo
}
